import axios from "axios";
import { messageUtils } from "assets/js/messageUtils";
import router from "../router/index.js";
import store from "store/index";
//导入NProgress进度条
import NProgress from "nprogress";
import "nprogress/nprogress.css";
import utils from "assets/js/utils";

// //导出function可以导出多个,而default只能导出一个
// //1.同时传入config配置,success和failure回调函数
// export function request(config, success, failure) {
//   //1.创建axios的实例
//   const instance = axios.create({
//     baseURL: "http://152.136.185.210:7878/api/m5",
//     timeout: 5000
//   });
//   //发送真正的网络请求
//   instance(config)
//     .then(res => {
//     //   console.log(res);
//       success(res); //回调函数
//     })
//     .catch(err => {
//     //   console.log(err);
//       failure(err); //回调函数
//     });
// }

// //2.只传入config配置,但里面包含success和failure回调函数
// export function request(config) {
//   //1.创建axios的实例
//   const instance = axios.create({
//     baseURL: "http://152.136.185.210:7878/api/m5",
//     timeout: 5000
//   });
//   //发送真正的网络请求
//   instance(config.baseConfig)
//     .then(res => {
//       //   console.log(res);
//       config.success(res); //回调函数
//     })
//     .catch(err => {
//       //   console.log(err);
//       config.failure(err); //回调函数
//     });
// }

// // //3.使用promise包装并返回Promise
// export function request(config) {
//   return new Promise((resolve, reject) => {
//     //1.创建axios的实例
//     const instance = axios.create({
//       baseURL: "http://152.136.185.210:7878/api/m5",
//       timeout: 5000
//     });
//     //发送真正的网络请求
//     instance(config)
//       .then(res => {
//         resolve(res);
//       })
//       .catch(err => {
//         reject(err);
//       });
//   });
// }
//4.直接返回实例instance,axios.create的继承的接口最终的返回的就是Promise
export function request(config) {
  //1.创建axios的实例
  const instance = axios.create({
    baseURL: "http://localhost:5000/api",
    timeout: 8000, //单次请求的超时时间
    retry: 0, //重新请求次数,可设置2-5次
    retryDelay: 1000, //重新请求的时间间隔
  });
  //2.axios的拦截器
  //2.1请求拦截的作用
  instance.interceptors.request.use(
    //请求成功
    (config) => {
      //显示NProgress进度条
      NProgress.start();
      // console.log(config);
      //1.比如config中的一些信息不符合服务器的要求
      //2.比如每次发送网络请求时,都希望在界面中显示一个请求的图标或遮罩层
      //3.某些网络请求(比如登录(token)),必须携带一些特殊的信息
      // //为请求头对象,添加Token验证的Authorization字段
      const tokenInfoModel = JSON.parse(window.sessionStorage.getItem("token"));
      // const tokenInfoModel = store.state.user.tokenInfoModel;
      config.headers.Authorization = tokenInfoModel?.token;
      //拦截到config之后要将config返回
      return config;
    },
    //请求失败
    (err) => {
      console.log(err);
    }
  );
  //2.2响应拦截
  instance.interceptors.response.use(
    (result) => {
      //隐藏NProgress进度条
      NProgress.done();
      // console.log(result);
      //请求成功后,刷新token的刷新时间
      utils.saveRefreshTime();
      //拦截到结果后要返回,可以只返回我们需要的data
      return result.data;
    },
    //处理错误
    (err) => {
      if (err.response !== undefined) {
        if (err.response.status === 401) {
          // ElMessage.error({
          //   showClose: true,
          //   message: "登录状态过期,请重新登录"
          // });
          var curTime = new Date();
          const tokenInfoModel = JSON.parse(window.sessionStorage.getItem("token"));
          const refreshTime = new Date(tokenInfoModel.refreshTime);
          if (refreshTime && curTime < refreshTime) {
            console.log("登录状态过期，正在刷新登录状态");
            //直接将整个请求return出去
            //刷新token
            return instance({
              method: "get",
              url: `/user/refresh/${tokenInfoModel.token}`,
            }).then(
              (res) => {
                if (res.success) {
                  messageUtils.notificationSuccess("refreshToken success! loading data...");
                  //记录过期时间和刷新时间
                  const curTime = new Date();
                  res.response.expirationTime = new Date(curTime.setSeconds(curTime.getSeconds() + res.response.expiration));
                  res.response.refreshTime = res.response.expirationTime;
                  //存储新的token
                  res.response.token = res.response.tokenType + " " + res.response.token;
                  store.commit("user/setUserInformation", res.response);

                  err.config.__isRetryRequest = true;
                  return instance(err.config);
                } else return Promise.reject(res.msg);
              },
              (err) => {
                // //清除保存的全部sessionStorage
                // window.sessionStorage.clear();
                // //清除保存的token
                store.commit("user/setUserInformation", ""); //清空vuex和sessionStorage中存储的token
                const activePath = window.sessionStorage.getItem("activePath"); //从sessionStorage中获取激活的路径
                // //跳转回登录页
                // location.href = "/login";
                if (activePath) return router.push(`/login?redirect=${activePath}`);
                return router.push("/login");
                // return Promise.reject("登录状态过期,请重新登录");
              }
            );
          } else {
            messageUtils.messageError("登录状态过期，请重新登录");
            return router.push("/login");
          }
        }
      }
      //超时处理,重新请求
      var config = err.config;
      if (!config || !config.retry) return Promise.reject(err);
      // 设置用于跟踪重试次数的变量
      config.__retryCount = config.__retryCount || 0;

      // 检查我们是否已将重试总数最大化
      if (config.__retryCount >= config.retry) {
        messageUtils.messageError("请求失败");
        // 错误拒绝,返回
        return Promise.reject(err);
      }

      // 增加重试次数
      config.__retryCount += 1;

      // 创造新的承诺来处理指数退避
      var backOff = new Promise(function (resolve) {
        setTimeout(function () {
          resolve();
        }, config.retryDelay || 1);
      });

      // 返回承诺，其中将撤回axios以重试请求
      return backOff.then(function () {
        // console.log("尝试重新请求" + config.__retryCount + "次");
        return instance(config);
      });
    }
  );
  //3.发送真正的网络请求
  return instance(config);
}
